<template>
  <div>
    <n-grid class="mt-4" cols="1 s:1 m:1 l:3 xl:3 2xl:3" responsive="screen" :x-gap="12">
      <n-gi span="1">
        <n-card :segmented="{ content: 'hard' }" :bordered="false" size="small">
          <template #header>
            <n-space>
              <n-dropdown trigger="hover" @select="selectAddMenu" :options="addMenuOptions">
                <n-button type="info" ghost icon-placement="right">
                  添加菜单
                  <template #icon>
                    <div class="flex items-center">
                      <n-icon size="14">
                        <DownOutlined />
                      </n-icon>
                    </div>
                  </template>
                </n-button>
              </n-dropdown>
              <n-button type="info" ghost icon-placement="left" @click="packHandle">
                全部{{ expandedKeys.length ? '收起' : '展开' }}
                <template #icon>
                  <div class="flex items-center">
                    <n-icon size="14">
                      <AlignLeftOutlined />
                    </n-icon>
                  </div>
                </template>
              </n-button>
              <n-button type="error" ghost icon-placement="left" @click="deleteMenu">
                删除
                <template #icon>
                  <div class="flex items-center">
                    <n-icon size="14">
                      <DeleteFilled />
                    </n-icon>
                  </div>
                </template>
              </n-button>
              <n-switch v-model:value="cascade" size="small">
                <template #checked>级联</template>
                <template #unchecked>单选</template>
              </n-switch>
            </n-space>
          </template>
          <div class="w-full menu">
            <n-input type="input" v-model:value="pattern" placeholder="输入菜单名称搜索">
              <template #suffix>
                <n-icon size="18" class="cursor-pointer">
                  <SearchOutlined />
                </n-icon>
              </template>
            </n-input>
            <div class="py-3 menu-list">
              <template v-if="loading">
                <div class="flex items-center justify-center py-4">
                  <n-spin size="medium" />
                </div>
              </template>
              <template v-else>
                <n-tree
                  block-line
                  :cascade="cascade"
                  checkable
                  :virtual-scroll="true"
                  :pattern="pattern"
                  :data="treeData"
                  :expandedKeys="expandedKeys"
                  :checked-keys="selectedKeys"
                  style="max-height: 650px; overflow: hidden"
                  @update:selected-keys="selectedTree"
                  @update:expanded-keys="onExpandedKeys"
                  @update:checked-keys="changeSelect"
                />
              </template>
            </div>
          </div>
        </n-card>
      </n-gi>
      <n-gi span="2">
        <n-card :segmented="{ content: 'hard' }" :bordered="false" size="small">
          <template #header>
            <n-space>
              <n-icon size="18">
                <FormOutlined />
              </n-icon>
              <span>编辑菜单{{ treeItemTitle ? `：${treeItemTitle}` : '' }}</span>
            </n-space>
          </template>
          <n-alert type="info" closable> 从菜单列表选择一项后，进行编辑</n-alert>
          <n-form
            :model="formParams"
            :rules="rules"
            ref="formRef"
            label-placement="left"
            :label-width="100"
            v-if="isEditMenu"
            class="py-4"
          >
            <n-form-item label="类型" path="type">
              <span>
                <n-icon size="14"> <MenuFoldOutlined /> </n-icon
                >{{
                  formParams.type === 0 ? '目录' : formParams.type === 1 ? '页面菜单' : '按钮'
                }}</span
              >
            </n-form-item>
            <n-form-item label="上级菜单" path="parentId">
              <menu-select-tree :title="parentTitle" @changeMenu="getSelectMenuData" />
            </n-form-item>
            <n-form-item label="菜单标题" path="title">
              <n-input placeholder="请输入菜单标题" v-model:value="formParams.title" />
            </n-form-item>
            <n-form-item label="菜单名称" path="name">
              <n-input placeholder="请输入菜单名称" v-model:value="formParams.name" />
            </n-form-item>
            <n-form-item
              label="路径"
              path="path"
              v-if="formParams.level === 1 || formParams.level === 2"
            >
              <n-input placeholder="请输入路径" v-model:value="formParams.path" />
            </n-form-item>
            <n-form-item label="重定向地址" path="redirect" v-if="formParams.level === 1">
              <n-input placeholder="请输入路径" v-model:value="formParams.redirect" />
            </n-form-item>
            <n-form-item
              label="前端组件"
              path="component"
              v-if="formParams.level === 1 || formParams.level === 2"
            >
              <n-input placeholder="请输入前端组件" v-model:value="formParams.component" />
            </n-form-item>
            <n-form-item
              label="是否缓存"
              prop="keepAlive"
              v-if="formParams.level === 1 || formParams.level === 2"
            >
              <n-radio-group v-model:value="formParams.keepAlive">
                <n-space>
                  <n-radio :value="0">否</n-radio>
                  <n-radio :value="1">是</n-radio>
                </n-space>
              </n-radio-group>
            </n-form-item>
            <n-form-item
              label="图标"
              path="icon"
              v-if="formParams.type === 0 || formParams.type === 1"
            >
              <n-input placeholder="请输入前端组件" v-model:value="formParams.icon" />
            </n-form-item>
            <n-form-item label="排序" path="sort">
              <n-input-number v-model:value="formParams.sort" clearable />
            </n-form-item>
            <n-form-item
              label="菜单权限"
              path="permission"
              v-if="formParams.type === 1 || formParams.type === 2"
            >
              <n-input
                placeholder="请输入权限，多个权限用，分割"
                v-model:value="formParams.permission"
              />
            </n-form-item>
            <n-form-item label="备注" path="remark">
              <n-input v-model:value="formParams.remark" type="textarea" placeholder="备注" />
            </n-form-item>
            <n-form-item path="auth" style="margin-left: 100px">
              <n-space>
                <n-button type="primary" :loading="subLoading" @click="formSubmit"
                  >保存修改</n-button
                >
                <n-button @click="handleReset">重置</n-button>
              </n-space>
            </n-form-item>
          </n-form>
        </n-card>
      </n-gi>
    </n-grid>
    <n-drawer v-model:show="isDrawer" :width="450" placement="right" @update:show="clearForm">
      <n-drawer-content :title="drawerTitle" closable>
        <n-form
          :model="formAdd"
          :rules="rules"
          ref="addFromRef"
          label-placement="left"
          :label-width="100"
        >
          <n-form-item label="类型" path="type">
            <span>{{
              formAdd.type === 0 ? '目录' : formAdd.type === 1 ? '页面菜单' : '按钮'
            }}</span>
          </n-form-item>
          <n-form-item label="菜单标题" path="title">
            <n-input placeholder="请输入菜单标题" v-model:value="formAdd.title" />
          </n-form-item>
          <n-form-item label="菜单名称" path="name">
            <n-input placeholder="请输入菜单名称" v-model:value="formAdd.name" />
          </n-form-item>
          <n-form-item label="路径" path="path" v-if="formAdd.level === 1 || formAdd.level === 2">
            <n-input placeholder="请输入路径" v-model:value="formAdd.path" />
          </n-form-item>
          <n-form-item label="重定向地址" path="redirect" v-if="formAdd.level === 1">
            <n-input placeholder="请输入路径" v-model:value="formAdd.redirect" />
          </n-form-item>
          <n-form-item
            label="前端组件"
            path="component"
            v-if="formAdd.level === 1 || formAdd.level === 2"
          >
            <n-input placeholder="请输入前端组件" v-model:value="formAdd.component" />
          </n-form-item>
          <n-form-item
            label="是否缓存"
            prop="keepAlive"
            v-if="formAdd.level === 1 || formAdd.level === 2"
          >
            <n-radio-group v-model:value="formAdd.keepAlive">
              <n-space>
                <n-radio :value="0">否</n-radio>
                <n-radio :value="1">是</n-radio>
              </n-space>
            </n-radio-group>
          </n-form-item>
          <n-form-item label="图标" path="icon" v-if="formAdd.level === 1 || formAdd.level === 2">
            <n-input placeholder="请输入前端组件" v-model:value="formAdd.icon" />
          </n-form-item>
          <n-form-item label="排序" path="sort">
            <n-input-number v-model:value="formAdd.sort" clearable />
          </n-form-item>
          <n-form-item
            label="菜单权限"
            path="permission"
            v-if="formAdd.level === 2 || formAdd.level === 3"
          >
            <n-input
              placeholder="请输入权限，多个权限用，分割"
              v-model:value="formAdd.permission"
            />
          </n-form-item>
          <n-form-item label="备注" path="remark">
            <n-input v-model:value="formAdd.remark" type="textarea" placeholder="备注" />
          </n-form-item>
        </n-form>

        <template #footer>
          <n-space>
            <n-button type="primary" :loading="addFormLoading" @click="saveForm">提交</n-button>
            <n-button @click="handleResetForm">关闭</n-button>
          </n-space>
        </template>
      </n-drawer-content>
    </n-drawer>
  </div>
</template>
<script lang="ts" setup>
  import { ref, unref, reactive, onMounted, computed } from 'vue';
  import { useMessage, useDialog } from 'naive-ui';
  import {
    DownOutlined,
    MenuFoldOutlined,
    DeleteFilled,
    FileDoneOutlined,
    AlignLeftOutlined,
    SearchOutlined,
    FormOutlined,
  } from '@vicons/antd';
  import { getMenuList, saveMenu, updateMenu, removeMenu } from '@/api/system/menu';
  import { getTreeItem } from '@/utils';
  import MenuSelectTree from '@/components/MenuSelect/MenuSelectTree.vue';

  const rules = {
    title: {
      required: true,
      message: '请输入菜单标题',
      trigger: 'blur',
    },
    name: {
      required: true,
      message: '请输入菜单名称',
      trigger: 'blur',
    },
    path: {
      required: true,
      message: '请输入路径',
      trigger: 'blur',
    },
    component: {
      required: true,
      message: '请输入前端组件地址',
      trigger: 'blur',
    },
    icon: {
      required: true,
      message: '请输入icon图标',
      trigger: 'blur',
    },
    permission: {
      required: true,
      message: '请填写操作权限',
      trigger: 'blur',
    },
  };
  let addFormRules = {
    title: {
      required: true,
      message: '请输入菜单标题',
      trigger: 'blur',
    },
    name: {
      required: true,
      message: '请输入菜单名称',
      trigger: 'blur',
    },
    path: {
      required: true,
      message: '请输入路径',
      trigger: 'blur',
    },
    component: {
      required: true,
      message: '请输入前端组件地址',
      trigger: 'blur',
    },
    icon: {
      required: true,
      message: '请输入icon图标',
      trigger: 'blur',
    },
    permission: {
      required: true,
      message: '请填写操作权限',
      trigger: 'blur',
    },
  };
  const formRef: any = ref(null);
  const menuForm = ref();
  const message = useMessage();
  const dialog = useDialog();
  let treeItemKey = ref([]);
  const cascade = ref(false);
  let expandedKeys = ref([]);
  const addFormLoading = ref(false);
  const treeData = ref([]);
  const parentTitle = ref('');
  const loading = ref(true);
  const subLoading = ref(false);
  const isEditMenu = ref(false);
  const treeItemTitle = ref('');
  const pattern = ref('');
  let formAdd = ref({});
  const parentId = ref('');
  const level = ref(0);
  const isDrawer = ref(false);
  const drawerTitle = ref('');
  const addFromRef: any = ref(null);
  const selectedKeys = ref([]);
  const isAddSon = computed(() => {
    return !treeItemKey.value.length;
  });

  const addMenuOptions = ref([
    {
      label: '添加顶级菜单',
      key: 'home',
      disabled: false,
    },
    {
      label: '添加子菜单',
      key: 'son',
      disabled: isAddSon,
    },
  ]);

  let formParams = reactive({});
  function selectAddMenu(key: string) {
    drawerTitle.value = key === 'home' ? '添加顶栏菜单' : `添加子菜单：${treeItemTitle.value}`;
    let formAdd1 = {};
    if (key === 'home') {
      formAdd1 = Object.assign(formAdd, {
        type: 0,
        level: 1,
        parentId: 0,
        sort: 0,
        component: 'LAYOUT',
      });
    } else {
      let type = 0;
      if (formParams.level === 1) {
        type = 1;
      } else if (formParams.level === 2) {
        type = 2;
      } else if (formParams.level === 3) {
        message.warning('仅支持2级菜单目录');
        return;
      } else {
        type = 0;
      }
      if (formParams.level === 1) {
        formAdd1.path = '/';
        formAdd1.component = 'LAYOUT';
      }
      formAdd1 = {
        icon: '',
        type: type,
        parentId: formParams.key,
        level: formParams.level + 1,
        sort: 0,
      };
    }
    formAdd.value = Object.assign(formAdd.value, formAdd1);
    isDrawer.value = true;
  }
  function deleteMenu() {
    if (selectedKeys.value.length <= 0) {
      message.warning('请选择要删除的数据');
      return;
    }
    dialog.warning({
      title: '警告',
      content: '你确定要删除所选数据？删除后无法回复',
      positiveText: '确定',
      negativeText: '取消',
      onPositiveClick: () => {
        let ids = selectedKeys.value.join(',');
        removeMenu(ids).then((res) => {
          if (res) {
            message.success('删除成功');
            initMenuData();
          } else {
            message.error(res.message);
          }
        });
      },
      onNegativeClick: () => {
        selectedKeys.value = [];
      },
    });
  }
  function getSelectMenuData(value) {
    formParams.parentId = value;
  }
  function clearForm() {
    formAdd.value = {};
  }
  function selectedTree(keys) {
    if (keys.length) {
      const treeItem = getTreeItem(unref(treeData), keys[0]);
      treeItemKey.value = keys;
      treeItemTitle.value = treeItem.label;
      formParams = Object.assign(formParams, treeItem);
      parentTitle.value = treeItem.parentTitle;
      isEditMenu.value = true;
    } else {
      isEditMenu.value = false;
      treeItemKey.value = [];
      treeItemTitle.value = '';
    }
  }
  function handleResetForm() {
    addFromRef.value.restoreValidation();
    formAdd.value = Object.assign(formAdd.value, {});
    isDrawer.value = false;
  }
  function handleReset() {
    const treeItem = getTreeItem(unref(treeData), treeItemKey.value[0]);
    formParams = Object.assign(formParams, treeItem);
  }
  function changeSelect(keys) {
    selectedKeys.value = keys;
  }
  function formSubmit() {
    formRef.value.validate((errors: boolean) => {
      if (!errors) {
        subLoading.value = true;
        updateMenu(formParams).then((res) => {
          if (res) {
            message.success('操作成功');
            subLoading.value = false;
            initMenuData();
            clearForm();
          } else {
            subLoading.value = false;
            message.error(res.message);
          }
        });
      } else {
        message.error('请填写完整信息');
      }
    });
  }
  function saveForm() {
    addFromRef.value.validate((errors: boolean) => {
      if (!errors) {
        addFormLoading.value = true;
        saveMenu(formAdd.value).then((res) => {
          if (res) {
            message.success('操作成功');
            addFormLoading.value = false;
            initMenuData();
            isDrawer.value = false;
            clearForm();
          }
        });
      } else {
        message.error('请填写完整信息');
      }
    });
  }
  function packHandle() {
    if (expandedKeys.value.length) {
      expandedKeys.value = [];
    } else {
      expandedKeys.value = unref(treeData).map((item: any) => item.key as string) as [];
    }
  }
  function initMenuData() {
    getMenuList().then((res) => {
      treeData.value = res;
      loading.value = false;
    });
  }
  onMounted(async () => {
    initMenuData();
  });

  function onExpandedKeys(keys) {
    expandedKeys.value = keys;
  }
</script>
